package wci.frontend.pascal.parsers;

import static wci.frontend.pascal.PascalErrorCode.MISSING_COLON_EQUALS;
import static wci.frontend.pascal.PascalTokenType.COLON_EQUALS;
import static wci.intermediate.icodeimpl.ICodeNodeTypeImpl.ASSIGN;

import java.util.EnumSet;

import wci.frontend.Token;
import wci.frontend.pascal.PascalErrorCode;
import wci.frontend.pascal.PascalParserTD;
import wci.frontend.pascal.PascalTokenType;
import wci.intermediate.ICodeFactory;
import wci.intermediate.ICodeNode;
import wci.intermediate.TypeSpec;
import wci.intermediate.symtabimpl.Predefined;
import wci.intermediate.typeimpl.TypeChecker;

/**
 * <h1>AssignmentStatementParser</h1>
 * <p>
 * 解析一个赋值语句
 * </p>
 * <p>
 * Copyright (c) 2009 by Ronald Mak
 * For instructional purposes only. No warranties.
 * </p>
 */
public class AssignmentStatementParser extends StatementParser {
	private static final EnumSet<PascalTokenType> COLON_EQUALS_SET = 
			ExpressionParser.EXPR_START_SET.clone();
	static {
		COLON_EQUALS_SET.add(COLON_EQUALS);
		COLON_EQUALS_SET.addAll(StatementParser.STMT_FOLLOW_SET);
	}

	public AssignmentStatementParser(PascalParserTD parent) {
		super(parent);
	}
	//是否是一个函数为赋值目标
	private boolean isFunctionTarget = false;
	/**
	 * 解析如 a = xx+yy; 之类的赋值语句
	 * 会有左值/右值两个子节点，并且节点类型与左值类型保持一致
	 * @param token
	 *            第一个token，肯定是identifier了。
	 * @return 语句子树根节点
	 * @throws Exception
	 */
	public ICodeNode parse(Token token) throws Exception {
		ICodeNode assignNode = ICodeFactory.createICodeNode(ASSIGN);
		//交由变量解析左边的变量
		VariableParser variableParser = new VariableParser(this);
        ICodeNode targetNode =isFunctionTarget
                ? variableParser.parseFunctionNameTarget(token)
                : variableParser.parse(token);
        
        TypeSpec targetType = targetNode != null ? targetNode.getTypeSpec()
                                                 : Predefined.undefinedType;
		assignNode.addChild(targetNode);
		//等号处同步
		token = synchronize(COLON_EQUALS_SET);
		// 找不到赋值:=就报错，找到就吞噬
		if (token.getType() == COLON_EQUALS) {
			token = nextToken();
		} else {
			errorHandler.flag(token, MISSING_COLON_EQUALS, this);
		}
		// 解析赋值语句右边的表达式，将其子树作为赋值节点的第二个孩子
		ExpressionParser expressionParser = new ExpressionParser(this);
		ICodeNode exprNode = expressionParser.parse(token);
		assignNode.addChild(exprNode);
		//左值变量，右值表达式，是否能赋值兼容。
		 TypeSpec exprType = exprNode != null ? exprNode.getTypeSpec()
                 : Predefined.undefinedType;
		 if (!TypeChecker.areAssignmentCompatible(targetType, exprType)) {
			errorHandler.flag(token, PascalErrorCode.INCOMPATIBLE_TYPES, this);
		}
		assignNode.setTypeSpec(targetType);
		return assignNode;
	}
	//函数式的赋值
	public ICodeNode parseFunctionNameAssignment(Token token)
	        throws Exception
	{
	        isFunctionTarget = true;
	        return parse(token);
	}
}
